﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml;
#if L2S
using System.Data.Linq;
#endif

namespace ALinq.Mapping
{
    /// <summary>
    /// Represents the mapping between a domain object into a database table or view.
    /// </summary>
    public class TableMapping : ModelMapping
    {
        private ModelMappingCollection<TypeMapping, Type> types;
        private MemberInfo member;

        /// <summary>
        /// Initializes a new instance of the ALinq.Mapping.TableMapping class.
        /// </summary>
        /// <param name="entityType">A domain object type.</param>
        public TableMapping(Type entityType)
            : base( ModelMappingType.Table)
        {
            this.types = new ModelMappingCollection<TypeMapping, Type>(this, o => o.Type);
            if (!this.GetType().IsGenericType)
            {
                TypeMapping typeMapping = new TypeMapping(entityType);
                RowType = typeMapping;
            }
        }

        /// <summary>
        /// Gets name of the table or view.
        /// </summary>
        public string Name
        {
            get { return this.GetAttribute(() => Name); }
            set { this.SetAttribute(() => Name, value); }
        }

        /// <summary>
        /// Gets the underlying System.Reflection.MemberInfo.
        /// </summary>
        public MemberInfo Member
        {
            get
            {
                return this.member;
            }
            set
            {
                if (value == null)
                    throw Error.MemberValueCanNotNull(() => Member);

                this.member = value;
                this.SetAttribute("Member", value.Name);
            }
        }

        /// <summary>
        /// Gets the ALinq.Mapping.TypeMapping that describes the type of the rows of the table.
        /// </summary>
        public TypeMapping RowType
        {
            get { return types.SingleOrDefault(); }
            protected set
            {
                if (value == null)
                    throw Error.MemberValueCanNotNull("Type");

                types.Clear();
                types.Add(value);
            }
        }
    }

    /// <summary>
    /// Represents the mapping between a domain object into a database table or view.
    /// </summary>
    /// <typeparam name="TEntity">A domain object type.</typeparam>
    public class TableMapping<TEntity> : TableMapping
    {
        /// <summary>
        /// Initializes a new instance of the ALinq.Mapping.TableMapping&lt;TEntity&gt; class
        /// </summary>
        public TableMapping()
            : base(typeof(DataContext))
        {
            base.RowType = new TypeMapping<TEntity>();
        }

        /// <summary>
        /// Gets the ALinq.Mapping.TypeMapping&lt;TEntity&gt; that describes the type of the rows of the table.
        /// </summary>
        public new TypeMapping<TEntity> RowType
        {
            get { return (TypeMapping<TEntity>)base.RowType; }
        }
    }
}